a tool for shared writing and social publishing
1import { AtUri } from "@atproto/api";
2import { z } from "zod";
3import { makeRoute } from "../lib";
4import type { Env } from "./route";
5import { getDocumentURL } from "app/lish/createPub/getPublicationURL";
6import { normalizeDocumentRecord } from "src/utils/normalizeRecords";
7
8export type SearchPublicationDocumentsReturnType = Awaited<
9 ReturnType<(typeof search_publication_documents)["handler"]>
10>;
11
12export const search_publication_documents = makeRoute({
13 route: "search_publication_documents",
14 input: z.object({
15 publication_uri: z.string(),
16 query: z.string(),
17 limit: z.number().optional().default(10),
18 }),
19 handler: async (
20 { publication_uri, query, limit },
21 { supabase }: Pick<Env, "supabase">,
22 ) => {
23 // Get documents in the publication, filtering by title using JSON operator
24 // Also join with publications to get the record for URL construction
25 const { data: documents, error } = await supabase
26 .from("documents_in_publications")
27 .select(
28 "document, documents!inner(uri, data), publications!inner(uri, record)",
29 )
30 .eq("publication", publication_uri)
31 .ilike("documents.data->>title", `%${query}%`)
32 .limit(limit);
33
34 if (error) {
35 throw new Error(
36 `Failed to search publication documents: ${error.message}`,
37 );
38 }
39
40 const result = documents.map((d) => {
41 const normalizedDoc = normalizeDocumentRecord(d.documents.data, d.documents.uri);
42
43 return {
44 uri: d.documents.uri,
45 title: normalizedDoc?.title || (d.documents.data as { title?: string })?.title || "Untitled",
46 url: normalizedDoc
47 ? getDocumentURL(normalizedDoc, d.documents.uri, d.publications)
48 : `${d.documents.uri}`,
49 };
50 });
51
52 return { result: { documents: result } };
53 },
54});